﻿using System;
using Newtonsoft.Json.Linq;
using TrinityAPI.Base;
using TrinityAPI.Base.Tools;
using TrinityAPI.Base.Models;
using DouYin.Open.Platform.Tools;

namespace DouYin.Open.Platform.ERP
{
    public class GetOrderSensitive : IAction
    {
        public JToken Invoke(JObject dataset, params JToken[] args)
        {
            var query = dataset.GetJsonObject("query");
            var constant = dataset.GetJsonObject("constant");

            string eShopCode = query.GetJsonObjectStringValue("access_token");
            string appkey = query.GetJsonObjectStringValue("app_key");

            var douyinAPIConfig = constant.GetJsonObject("douyinAPIConfig");
            var eshopAPIConfig = douyinAPIConfig.GetJsonObject("eshops").GetJsonObject(eShopCode);
            string url = douyinAPIConfig.GetJsonObjectStringValue("url");
            string secret = eshopAPIConfig.GetJsonObjectStringValue("app_secret");
            var timeout = eshopAPIConfig.GetJsonObjectIntValue("timeout", 60000);
            var proxy = eshopAPIConfig.GetJsonObjectValue("proxy");

            if (string.IsNullOrWhiteSpace(eShopCode))
                throw new BaseException("@20001", "");

            if (string.IsNullOrWhiteSpace(url) || string.IsNullOrWhiteSpace(appkey) || string.IsNullOrWhiteSpace(secret))
                throw new BaseException("@20002", "");

            try
            {
                var requestString = dataset.GetJsonObjectStringValue("requestString");
                var orderInfo = new APIRequest().Invoke(new JObject()
                {
                    { "query", query },
                    { "requestString", requestString },
                    { "constant", constant }
                }) as JObject;

                var orderDetail = orderInfo.GetJsonObject("data").GetJsonObject("shop_order_detail");
                var postAddress = orderDetail.GetJsonObject("post_addr");

                if (orderDetail != null && postAddress != null)
                {
                    string order_id = orderDetail.GetJsonObjectStringValue("order_id");
                    string encrypt_post_receiver = orderDetail.GetJsonObjectStringValue("encrypt_post_receiver");
                    string encrypt_post_tel = orderDetail.GetJsonObjectStringValue("encrypt_post_tel");
                    string encrypt_address_detail = postAddress.GetJsonObjectStringValue("encrypt_detail");

                    var cipherInfos = new JArray();
                    cipherInfos.Add(new JObject
                    {
                        { "auth_id", order_id },
                        { "cipher_text", encrypt_post_receiver }
                    });
                    cipherInfos.Add(new JObject
                    {
                        { "auth_id", order_id },
                        { "cipher_text", encrypt_post_tel }
                    });
                    cipherInfos.Add(new JObject
                    {
                        { "auth_id", order_id },
                        { "cipher_text", encrypt_address_detail }
                    });

                    string accessToken = GetAccessToken.GetToken(eShopCode, constant);
                    string strParam = Newtonsoft.Json.JsonConvert.SerializeObject(ApiUtils.KeySort(new JObject() { { "cipher_infos", cipherInfos } }));

                    string api = null;
                    string version = "2";
                    string method = "order.batchDecrypt";
                    string sign_method = "hmac-sha256";
                    string timestamp = ApiUtils.GetTimeStamp(DateTime.Now).ToString();
                    query["api"] = api;
                    query["method"] = method;
                    query["version"] = version;
                    query["timestamp"] = timestamp;
                    query["sign_method"] = sign_method;
                    query["sign"] = ApiUtils.Sign(appkey, secret, method, timestamp, version, strParam);

                    var decryptData = new APIRequest().Invoke(new JObject()
                    {
                        { "query", query },
                        { "requestString", strParam },
                        { "constant", constant }
                    }) as JObject;

                    if (decryptData.GetJsonObjectIntValue("code", 1) != 10000)
                    {
                        LogHelper.Info("get order sensitive request: " + strParam);
                        LogHelper.Info("get order sensitive response: " + decryptData.ToString(Newtonsoft.Json.Formatting.None));
                        string msg = decryptData.GetJsonObjectStringValue("msg");
                        string sub_msg = decryptData.GetJsonObjectStringValue("sub_msg");
                        throw ExceptionHelper.GenException("@20004", msg + (string.IsNullOrWhiteSpace(sub_msg) ? "" : "-" + sub_msg));
                    }

                    var decryptInfos = decryptData.GetJsonObject("data").GetJsonObjectValue("decrypt_infos") as JArray;
                    if (decryptInfos == null || decryptInfos.Count == 0)
                        throw ExceptionHelper.GenException("@20004", "nothing response");

                    foreach (var item in decryptInfos)
                    {
                        var info = item as JObject;
                        if (info == null || info.GetJsonObjectIntValue("err_no", 1) != 0)
                            throw ExceptionHelper.GenException("@20004", info.GetJsonObjectStringValue("err_msg"));
                        if (info.GetJsonObjectStringValue("cipher_text") == encrypt_post_receiver)
                            orderDetail["post_receiver"] = info.GetJsonObjectStringValue("decrypt_text");
                        else if (info.GetJsonObjectStringValue("cipher_text") == encrypt_post_tel)
                            orderDetail["post_tel"] = info.GetJsonObjectStringValue("decrypt_text");
                        else if (info.GetJsonObjectStringValue("cipher_text") == encrypt_address_detail)
                            postAddress["detail"] = info.GetJsonObjectStringValue("decrypt_text");
                    }
                }
                return orderInfo;
            }
            catch(BaseException ex)
            {
                if (!string.IsNullOrEmpty(ex.Message))
                    throw ex;
                throw new Exception(ex.Code);
            }
            catch (Exception ex)
            {
                LogHelper.Info("GetOrderSensitive fail: " + ex.Message);
                throw new Exception("@20000");
            }
        }
    }
}
